#include "main.h"

//*********************************************************************************************************************************
//**********************************************************主线程函数***************************************************************
extern sqlite3*db;
extern int epoll_listen1;
void*server_TCP_fun(void*arg)
{
    //创建返回事件列表
    struct epoll_event epollbuf[50]={0};
    printf("阻塞等待客户端数据请求...");fflush(stdout);
    while(1)
    {
        int len=epoll_wait(epoll_listen1,epollbuf,50,-1);
        printf("\n检测到客户端请求,数量=%d\n",len);
        struct tcp_data from_buf={0};struct user_data test_userid={0};
        for(int i=0;i<len;i++)
        {
            test_userid.C=epollbuf[i].data.fd;
            printf("##开始处理<%d>的请求---->:",test_userid.C);
            int ret=read(test_userid.C,&from_buf.type,4);
            printf("%d\n",from_buf.type);

            if(ret==0)
            {
                //更新账户表单(下线)
                edit1_DB(db,4,test_userid);
                //更新账户表单(下线)
                epoll_ctl(epoll_listen1,EPOLL_CTL_DEL,test_userid.C,NULL);
                printf("##客户端<%d>断开连接\n",test_userid.C);
                printf("\n\n阻塞等待客户端数据请求...");fflush(stdout);
                continue;
            }
            if(from_buf.type==1000)
            {
                //数据同步
                pthread_t server_tcp1;
                pthread_create(&server_tcp1,NULL,server_tcp_fun01,&test_userid);
            }
            else if(from_buf.type>=2000 && from_buf.type<2099)
            {
                //shell指令
                epoll_ctl(epoll_listen1,EPOLL_CTL_DEL,test_userid.C,NULL);
                pthread_t server_tcp2;
                pthread_create(&server_tcp2,NULL,server_shell_fun01,&test_userid.C);
            }
            else if(from_buf.type>=2100 && from_buf.type<2199)
            {
                //文件上传
                upload_ser(test_userid,&from_buf);

            }
            else if(from_buf.type>=2200 && from_buf.type<2299)
            {
                //文件下载
                epoll_ctl(epoll_listen1,EPOLL_CTL_DEL,test_userid.C,NULL);
                pthread_t server_tcp2;
                pthread_create(&server_tcp2,NULL,server_shell_fun02,&test_userid);

            }
            else if(from_buf.type==3000)
            {

            }
            else
                while(1);
            
        }


    }
}

//*********************************************************************************************************************************
//**********************************************************数据同步线程函数**********************************************************
void*server_tcp_fun01(void*arg)
{
    //***********************************************读取用户个人数据*********************************************************
    //查询该客户端的账号名
    struct user_data*temp_userid=(struct user_data*)arg;
    if(inquire1_DB(db,NULL,temp_userid->C,temp_userid)==-1){printf("无此用户相关数据\n");return NULL;}
    //读取该用户相关数据
    //sqlite3* user_db=NULL;
    //sqlite3_open(temp_userid.name,&user_db);
    struct contact_link*P=malloc(sizeof(struct contact_link));
    //printf("创建头节点:%p\n",P);
    P->len=0,P->tail=P;P->next=NULL;
    char test[500]={0};char*errmsg=NULL;
    sprintf(test,"select * from %s ;",temp_userid->name);
    //printf("sqlite3语句:%s\n",test);
    int ret;
	if((ret=sqlite3_exec(db,test,callback2,P,&errmsg))!=SQLITE_OK){printf("执行sqlite3语句7出错%d%s\n",ret,errmsg);return NULL;}
    struct contact_link*temp=P->next;
    //销毁链表头节点
    //printf("销毁头节点%p\n",P);
    free(P);
    struct tcp_data to_buf={0};to_buf.size=0;to_buf.type=1000;
    //***************************************************开始同步*********************************************************
    while(temp!=NULL)
    {         
        //判断当前buf剩余空间是否够用(size+type+name长度+name)
        if(to_buf.size+4+2+sizeof(temp->contact_data.name)>4096)
            {
                write(temp_userid->C,&to_buf,to_buf.size+28);
                printf("同步标志:%d 同步包大小:%d\n",to_buf.type,to_buf.size);
                to_buf.size=0;to_buf.type=1001;
            }
        //printf("同步联系人:<%s>类型:%d  \n",temp->contact_data.name,temp->contact_data.type);
        //type
        memcpy(to_buf.buf+to_buf.size,&(temp->contact_data.type),4);
        to_buf.size+=4;
        //name长度
        short nmae_size=strlen(temp->contact_data.name)+1;
        memcpy(to_buf.buf+to_buf.size,&nmae_size,2);
        to_buf.size+=2;
        //name本身
        memcpy(to_buf.buf+to_buf.size,temp->contact_data.name,nmae_size);
        to_buf.size+=nmae_size;
        //销毁已读取节点
        struct contact_link*PP=temp;
        temp=temp->next;
        //printf("开始销毁节点%p\n",PP);
        free(PP);
        PP=NULL;
    }
    printf("同步标志:%d 同步包大小:%d\n",to_buf.type,to_buf.size);
    write(temp_userid->C,&to_buf,to_buf.size+28);
    to_buf.size=0;to_buf.type=1002;//结束标志，同步完成
    printf("同步标志:%d 同步包大小:%d\n",to_buf.type,to_buf.size);
    write(temp_userid->C,&to_buf,28);
    printf("\n\n阻塞等待客户端数据请求...");fflush(stdout);
    return NULL;
}
int callback2(void*arg,int argc,char**argv,char**col)
{
	//printf("查询到字段数%d\n",argc);
	struct contact_link* P=(struct contact_link*)arg;
	struct contact_link*P1=malloc(sizeof(struct contact_link));

	strcpy(P1->contact_data.name,argv[0]);
	P1->contact_data.type=atoi(argv[1]);
    //printf("创建新节点%p\n",P1);
    printf("姓名:%s  类型:%d\n",P1->contact_data.name,P1->contact_data.type);
	P->tail->next=P1;
    P->tail=P1;
    P1->next=NULL;
    P->len++;
	return 0;
}

//*********************************************************************************************************************************
//**********************************************************shell指令线程函数*********************************************************
extern int epoll_listen1;
void*server_shell_fun01(void*arg)
{
    int C = *(int*)arg;
    struct tcp_data data_buf={0};
    data_buf.type=2001;
    read(C,&data_buf.size,4);
    read(C,&data_buf.name,20);
    read(C,&data_buf.buf,data_buf.size);
    printf("客户端<%s>shell命令大小为%d->:<%s>\n",data_buf.name,data_buf.size,data_buf.buf);
    char*shell_arg[64]={0};
    shell_arg[0]=strtok(data_buf.buf," ");
    int i=1;    
    while((shell_arg[i]=strtok(NULL," "))!=NULL)
        i++;
    printf("客户端<%s>shell命令大小为%d->:<%s>\n",data_buf.name,data_buf.size,data_buf.buf);   
    int fd[2];
    if(pipe(fd)<0){printf("创建管道失败1\n");return NULL;}
    pid_t pid = fork();
    if(pid>0)
    {
        close(fd[1]);
        printf("反馈shell结果为:\n");
        while(read(fd[0],data_buf.buf,4096)>0)
        {
            printf("<%s>\n",data_buf.buf);
            data_buf.size=strlen(data_buf.buf)+1;
            data_buf.buf[strlen(data_buf.buf)-1]='\0';
            write(C,&data_buf,data_buf.size+28);
        }
        data_buf.type=2999;
        write(C,&data_buf,28);
        close(fd[0]);
        waitpid(pid,NULL,0);
        struct epoll_event epoll_data={0};epoll_data.events=EPOLLIN;epoll_data.data.fd=C;
        epoll_ctl(epoll_listen1,EPOLL_CTL_ADD,C,&epoll_data);
    }
    else
    {
        close(fd[0]);
        dup2(fd[1],1);
        dup2(fd[1],2);
        execvp(shell_arg[0],shell_arg);
        printf("未找到命令\"%s\"\n",data_buf.buf);
        close(fd[1]);
    }
}

//*********************************************************************************************************************************
//**********************************************************下载文件线程函数*********************************************************
extern int epoll_listen1;
void*server_shell_fun02(void*arg)
{
    int C = *(int*)arg;
    struct tcp_data data_buf={0};
    data_buf.type=2200;
    printf("开始读取-\n");
    read(C,&data_buf.size,4);
    printf("大小为:%d\n",data_buf.size);
    read(C,&data_buf.name,20);
    read(C,&data_buf.buf,data_buf.size);
    printf("客户端<%s>shell命令大小为%d->:<%s>\n",data_buf.name,data_buf.size,data_buf.buf);
    char*shell_arg[64]={0};
    char tempbuf[4096]={0};
	memcpy(tempbuf,data_buf.buf,4096);
    shell_arg[0]=strtok(tempbuf," ");
    int i=1;    
    while((shell_arg[i]=strtok(NULL," "))!=NULL)
        i++;
    for(int n=1;n<i;n++)
	{
		printf("开始处理<%s>\n",shell_arg[n]);
;		long temp_size=0;
		long file_size=0;
		struct  stat file_date;
		printf("upload <%s>",shell_arg[n]);
		if(access(shell_arg[n],F_OK)==-1){printf("upload %s:该文件不存在\n",shell_arg[n]);continue;}
		if(stat(shell_arg[n],&file_date)==-1){perror("获取文件属性失败");continue;}
		file_size=file_date.st_size;
		int FP=open(shell_arg[n],O_RDONLY|O_EXCL);
		if(FP==-1){perror("打开文件失败");continue;}
		//printf("已传输:%ld   总量:%ld\n",temp_size,file_size);
		//存储文件名+总大小
		data_buf.type=2200;
		short len=strlen(shell_arg[n])+2;
		memcpy(data_buf.buf,&len,2);
		memcpy(data_buf.buf+2,shell_arg[n],len);
		int dd=0;double dd_d=0;
		char dd_f[51]={0};
		printf("大小<%ld>\n",file_size+2+len);
		printf("\r拷贝进度:[%-50s]%d%%",dd_f,dd);fflush(stdout);
		while(temp_size<file_size)
		{
			int ret=read(FP,data_buf.buf+2+len,4096-2-len);
			if(ret==0)continue;
			data_buf.size=ret+2+len;
			write(C,&data_buf,data_buf.size+28);
			temp_size+=ret;
			//界面优化
			dd_d=(double)(file_size-temp_size)/file_size;dd=100-(int)(dd_d*100);
			//printf("已拷贝:%ld--总量:%ld\n拷贝进度:%d\n",temp_size,file_date.st_size,dd);
			for(int i=0;i<dd/2;i++)
			{
				dd_f[i]='#';
			}
			dd_f[50]='\0';
			printf("\r拷贝进度:[%-50s]%d%%",dd_f,dd);fflush(stdout);
			usleep(10000);
			data_buf.type=2201;
		}
		close(FP);
		printf("拷贝完成\n");
	}
    struct epoll_event epoll_data={0};epoll_data.events=EPOLLIN;epoll_data.data.fd=C;
    epoll_ctl(epoll_listen1,EPOLL_CTL_ADD,C,&epoll_data);
}
    

